package com.tanhua.login.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.login.mapper.AdminMapper;
import com.tanhua.login.pojo.Admin;
import com.tanhua.login.service.UserService;
import com.tanhua.login.vo.AdminVo;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.joda.time.DateTime;

import java.io.IOException;
import java.sql.Struct;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private AdminMapper adminMapper;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Value("${jwt.secret}")
    private String secret;

    /**
     * 用户登录
     *
     * @param username
     * @param password
     * @param verificationCode
     * @param uuid
     * @return
     */
    @Override
    public String login(String username, String password, String verificationCode, String uuid) {

        //判断用户名是否为空
        if (StrUtil.isEmpty(username)) {
            return null;
        }

        //判断密码是否为空
        if (StrUtil.isEmpty(password)) {
            return null;
        }

        //通过用户名查询用户信息
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        Admin admin = adminMapper.selectOne(queryWrapper);

        //判断用户是否为空,如果为空则说明数据库没有该用户
        if (admin == null) {
            return null;
        }

        //密码需要通过MD5加密
        String pwd = DigestUtils.md5Hex(password);

        //如果不为空则判断密码是否正确
        if (!StrUtil.equals(admin.getPassword(), pwd)) {
            return null;
        }

        String redisKey = "MANAGE_CAP_" + uuid;
        String code = redisTemplate.opsForValue().get(redisKey);
        //首先判断验证码是否为空
        if (StrUtil.isEmpty(code)) {
            return null;
        }

        //如果不为空则判断用户输入的验证码是否正确(不区分大小写)
        if (!StringUtils.equalsIgnoreCase(verificationCode, code)) {
            return null;
        }

        //如果正确就在校验后把验证码删除
        redisTemplate.delete(redisKey);

        try {

            //生成token
            Map<String, Object> claims = new HashMap<String, Object>();
            claims.put("username", admin.getUsername());
            claims.put("id", admin.getId());
            String token = Jwts.builder()
                    .setClaims(claims) //payload，存放数据的位置，不能放置敏感数据，如：密码等
                    .signWith(SignatureAlgorithm.HS256, secret) //设置加密方法和加密盐
                    .compact();

            // 将token存储到redis中
            String redisTokenKey = "CACHE_KEY_TOKEN_LOGIN_" + token;

            //System.out.println(redisTokenKey);
            //密码不参与序列化,在前端页面查看不到
            admin.setPassword(null);
            //System.out.println(admin);
            //序列化到json
            String redisTokenValue = MAPPER.writeValueAsString(admin);
            //System.out.println(redisTokenValue);

            //设置过期时间为7天
            redisTemplate.opsForValue().set(redisTokenKey, redisTokenValue, Duration.ofDays(7));

            return token;
        } catch (Exception e) {
            log.error("存储token出错", e);
            return null;
        }
    }

    /**
     * 查询用户基本信息
     *
     * @param token
     * @return
     */
    @Override
    public AdminVo queryAdminByToken(String token) {
        String redisKey = "CACHE_KEY_TOKEN_LOGIN_" + token;

        //System.out.println(redisKey);
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //校验token
        if (StringUtils.isEmpty(redisValue)) {
            return null;
        }

        //设置redis中的过期时间
        redisTemplate.opsForValue().set(redisKey,redisValue,1,TimeUnit.DAYS);

        try {
            //通过json转换获取admin中的信息
            Admin admin = MAPPER.readValue(redisValue, Admin.class);
            //System.out.println(admin);

            //把admin中的信息写入adminVo中
            AdminVo adminVo = new AdminVo();
            adminVo.setUid(admin.getId());
            adminVo.setUsername(admin.getUsername());
            adminVo.setAvatar(admin.getAvatar());
            return adminVo;

        } catch (ExpiredJwtException e) {
            log.info("token已经过期！ token = " + token);
        }catch (Exception e){
            log.error("token不合法！ token = "+ token, e);
        }
        return null;
    }

    /**
     * 登出用户
     * @param token
     * @return
     */
    @Override
    public void logout(String token) {
        String redisKey = "CACHE_KEY_TOKEN_LOGIN_" + token;
        redisTemplate.delete(redisKey);
    }

}
